package com.jintu.portal.utils;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.*;

public class BeanUtils {

	private static final Logger log = LoggerFactory.getLogger(BeanUtils.class);
	/**
	 * 利用反射实现对象之间属性复制
	 * @param from
	 * @param to
	 */
	public static void copyProperties(Object from, Object to) throws Exception {
		copyPropertiesExclude(from, to, null);
	}

	/**
	 * 利用反射实现对象之间属性复制
	 * @param from
	 * @param clz
	 */
	public static <T> T copyProperties(Object from, Class<T> clz) throws Exception {
		T t = clz.newInstance();
		copyPropertiesExclude(from, t, null);
		return t;
	}

	public static <T> List<T> copyProperties(List list, Class<T> clz) throws Exception {
		ArrayList clzList = new ArrayList();
		Iterator iterator = list.iterator();
		while(iterator.hasNext()) {
			clzList.add(copyProperties(iterator.next(), clz));
		}
		return clzList;
	}
	
	/**
	 * 复制对象属性
	 * @param from
	 * @param to
	 * @param excludsArray 排除属性列表
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception {
		List<String> excludesList = null;
		if(excludsArray != null && excludsArray.length > 0) {
			excludesList = Arrays.asList(excludsArray);	//构造列表对象
		}
		Method[] fromMethods = from.getClass().getDeclaredMethods();
		Method[] toMethods = to.getClass().getDeclaredMethods();
		Method fromMethod = null, toMethod = null;
		Type fromReturnType = null;
		Type toReturnType = null;
		String fromMethodName = null, toMethodName = null;
		for (int i = 0; i < fromMethods.length; i++) {
			fromMethod = fromMethods[i];
			fromMethodName = fromMethod.getName();
			if (!fromMethodName.contains("get"))
				continue;
			//排除列表检测
			if(excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) {
				continue;
			}
			toMethodName = "set" + fromMethodName.substring(3);
			toMethod = findMethodByName(toMethods, toMethodName);
			if (toMethod == null)
				continue;
			fromReturnType = fromMethod.getGenericReturnType();
			toReturnType = toMethod.getGenericParameterTypes()[0];
			if(!fromReturnType.equals(toReturnType)) {
				continue;
			}
			Object value = fromMethod.invoke(from, new Object[0]);
			if(value == null)
				continue;
			if(value instanceof String && StringUtil.isEmpty(String.valueOf(value)))
				continue;
			if(value instanceof Integer && ((Integer) value).intValue() == 0) {
				continue;
			}
			//集合类判空处理
			if(value instanceof Collection) {
				Collection newValue = (Collection)value;
				if(newValue.size() <= 0)
					continue;
			}
			toMethod.invoke(to, new Object[] {value});
		}
	}
	
	/**
	 * 对象属性值复制，仅复制指定名称的属性值
	 * @param from
	 * @param to
	 * @param includsArray
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception {
		List<String> includesList = null;
		if(includsArray != null && includsArray.length > 0) {
			includesList = Arrays.asList(includsArray);	//构造列表对象
		} else {
			return;
		}
		Method[] fromMethods = from.getClass().getDeclaredMethods();
		Method[] toMethods = to.getClass().getDeclaredMethods();
		Method fromMethod = null, toMethod = null;
		String fromMethodName = null, toMethodName = null;
		for (int i = 0; i < fromMethods.length; i++) {
			fromMethod = fromMethods[i];
			fromMethodName = fromMethod.getName();
			if (!fromMethodName.contains("get"))
				continue;
			//排除列表检测
			String str = fromMethodName.substring(3);
			if(!includesList.contains(str.substring(0,1).toLowerCase() + str.substring(1))) {
				continue;
			}
			toMethodName = "set" + fromMethodName.substring(3);
			toMethod = findMethodByName(toMethods, toMethodName);
			if (toMethod == null)
				continue;
			Object value = fromMethod.invoke(from, new Object[0]);
			if(value == null)
				continue;
			//集合类判空处理
			if(value instanceof Collection) {
				Collection newValue = (Collection)value;
				if(newValue.size() <= 0)
					continue;
			}
			toMethod.invoke(to, new Object[] {value});
		}
	}
	
	

	/**
	 * 从方法数组中获取指定名称的方法
	 * 
	 * @param methods
	 * @param name
	 * @return
	 */
	public static Method findMethodByName(Method[] methods, String name) {
		for (int j = 0; j < methods.length; j++) {
			if (methods[j].getName().equals(name))
				return methods[j];
		}
		return null;
	}

	public static <T> T  convertMapToBean(Map<String, Object> map, Class<T> clz) throws Exception {
		T t = clz.newInstance();

		ConvertUtils.register(new LongConverter(null), Long.class);
		ConvertUtils.register(new ShortConverter(null), Short.class);
		ConvertUtils.register(new IntegerConverter(null), Integer.class);
		ConvertUtils.register(new DoubleConverter(null), Double.class);
		ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
		ConvertUtils.register(new DateTimeConverter(), Date.class);
		org.apache.commons.beanutils.BeanUtils.populate(t, map);

		return t;
	}

	public static <T> List<T>  convertMapToBean(List<Map<String, Object>> mapList, Class<T> clz) throws Exception {
		List list = new ArrayList(mapList.size());

		try {
			for (Map map : mapList) {
				list.add(BeanUtils.convertMapToBean(map, clz));
			}
		} catch (IllegalAccessException e) {
			log.error("系统异常",e);
		} catch (InstantiationException e) {
			log.error("系统异常",e);
		} catch (InvocationTargetException e) {
			log.error("系统异常",e);
		}
		return list;
	}
}
